home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Zoners Half-Life Tools / hlrad / lightmap.cpp < prev    next >
C/C++ Source or Header  |  2002-12-09  |  81KB  |  2,361 lines

  1. #include "qrad.h"
  2.  
  3. edgeshare_t     g_edgeshare[MAX_MAP_EDGES];
  4. vec3_t          g_face_centroids[MAX_MAP_EDGES];
  5. bool            g_sky_lighting_fix = DEFAULT_SKY_LIGHTING_FIX;
  6.  
  7. #define TEXTURE_STEP   16.0
  8.  
  9. // =====================================================================================
  10. //  PairEdges
  11. // =====================================================================================
  12. void            PairEdges()
  13. {
  14.     int             i, j, k;
  15.     dface_t*        f;
  16.     edgeshare_t*    e;
  17.  
  18.     memset(&g_edgeshare, 0, sizeof(g_edgeshare));
  19.  
  20.     f = g_dfaces;
  21.     for (i = 0; i < g_numfaces; i++, f++)
  22.     {
  23.         for (j = 0; j < f->numedges; j++)
  24.         {
  25.             k = g_dsurfedges[f->firstedge + j];
  26.             if (k < 0)
  27.             {
  28.                 e = &g_edgeshare[-k];
  29.  
  30.                 hlassert(e->faces[1] == NULL);
  31.                 e->faces[1] = f;
  32.             }
  33.             else
  34.             {
  35.                 e = &g_edgeshare[k];
  36.  
  37.                 hlassert(e->faces[0] == NULL);
  38.                 e->faces[0] = f;
  39.             }
  40.  
  41.             if (e->faces[0] && e->faces[1]) {
  42.             // determine if coplanar
  43.             if (e->faces[0]->planenum == e->faces[1]->planenum) {
  44.                     e->coplanar = true;
  45.             } else {
  46.                     // see if they fall into a "smoothing group" based on angle of the normals
  47.                     vec3_t          normals[2];
  48.  
  49.                     VectorCopy(getPlaneFromFace(e->faces[0])->normal, normals[0]);
  50.                     VectorCopy(getPlaneFromFace(e->faces[1])->normal, normals[1]);
  51.  
  52.                     e->cos_normals_angle = DotProduct(normals[0], normals[1]);
  53.  
  54.                     if (e->cos_normals_angle > (1.0 - NORMAL_EPSILON))
  55.                     {
  56.                         e->coplanar = true;
  57.                     }
  58.                     else if (g_smoothing_threshold > 0.0)
  59.                     {
  60.                         if (e->cos_normals_angle >= g_smoothing_threshold)
  61.                         {
  62.                             VectorAdd(normals[0], normals[1], e->interface_normal);
  63.                             VectorNormalize(e->interface_normal);
  64.                         }
  65.                     }
  66.                 }
  67.             }
  68.         }
  69.     }
  70. }
  71.  
  72. #define    MAX_SINGLEMAP    (18*18*4)
  73.  
  74. typedef struct
  75. {
  76.     vec_t*          light;
  77.     vec_t           facedist;
  78.     vec3_t          facenormal;
  79.  
  80.     int             numsurfpt;
  81.     vec3_t          surfpt[MAX_SINGLEMAP];
  82.  
  83.     vec3_t          texorg;
  84.     vec3_t          worldtotex[2];                         // s = (world - texorg) . worldtotex[0]
  85.     vec3_t          textoworld[2];                         // world = texorg + s * textoworld[0]
  86.  
  87.     vec_t           exactmins[2], exactmaxs[2];
  88.  
  89.     int             texmins[2], texsize[2];
  90.     int             lightstyles[256];
  91.     int             surfnum;
  92.     dface_t*        face;
  93. }
  94. lightinfo_t;
  95.  
  96. // =====================================================================================
  97. //  TextureNameFromFace
  98. // =====================================================================================
  99. static const char* TextureNameFromFace(const dface_t* const f)
  100. {
  101.     texinfo_t*      tx;
  102.     miptex_t*       mt;
  103.     int             ofs;
  104.  
  105.     //
  106.     // check for light emited by texture
  107.     //
  108.     tx = &g_texinfo[f->texinfo];
  109.  
  110.     ofs = ((dmiptexlump_t*)g_dtexdata)->dataofs[tx->miptex];
  111.     mt = (miptex_t*)((byte*) g_dtexdata + ofs);
  112.  
  113.     return mt->name;
  114. }
  115.  
  116. // =====================================================================================
  117. //  CalcFaceExtents
  118. //      Fills in s->texmins[] and s->texsize[]
  119. //      also sets exactmins[] and exactmaxs[]
  120. // =====================================================================================
  121. static void     CalcFaceExtents(lightinfo_t* l)
  122. {
  123.     const int       facenum = l->surfnum;
  124.     dface_t*        s;
  125.     vec_t           mins[2], maxs[2], val;
  126.     int             i, j, e;
  127.     dvertex_t*      v;
  128.     texinfo_t*      tex;
  129.  
  130.     s = l->face;
  131.  
  132.     mins[0] = mins[1] = 999999;
  133.     maxs[0] = maxs[1] = -99999;
  134.  
  135.     tex = &g_texinfo[s->texinfo];
  136.  
  137.     for (i = 0; i < s->numedges; i++)
  138.     {
  139.         e = g_dsurfedges[s->firstedge + i];
  140.         if (e >= 0)
  141.         {
  142.             v = g_dvertexes + g_dedges[e].v[0];
  143.         }
  144.         else
  145.         {
  146.             v = g_dvertexes + g_dedges[-e].v[1];
  147.         }
  148.  
  149.         for (j = 0; j < 2; j++)
  150.         {
  151.             val = v->point[0] * tex->vecs[j][0] +
  152.                 v->point[1] * tex->vecs[j][1] + v->point[2] * tex->vecs[j][2] + tex->vecs[j][3];
  153.             if (val < mins[j])
  154.             {
  155.                 mins[j] = val;
  156.             }
  157.             if (val > maxs[j])
  158.             {
  159.                 maxs[j] = val;
  160.             }
  161.         }
  162.     }
  163.  
  164.     for (i = 0; i < 2; i++)
  165.     {
  166.         l->exactmins[i] = mins[i];
  167.         l->exactmaxs[i] = maxs[i];
  168.  
  169.         mins[i] = floor(mins[i] / 16.0);
  170.         maxs[i] = ceil(maxs[i] / 16.0);
  171.  
  172.         l->texmins[i] = mins[i];
  173.         l->texsize[i] = maxs[i] - mins[i];
  174.     }
  175.  
  176.     if (!(tex->flags & TEX_SPECIAL))
  177.     {
  178.         if ((l->texsize[0] > 16) || (l->texsize[1] > 16))
  179.         {
  180.             ThreadLock();
  181.             PrintOnce("\nfor Face %d (texture %s) at ", s - g_dfaces, TextureNameFromFace(s));
  182.  
  183.             for (i = 0; i < s->numedges; i++)
  184.             {
  185.                 e = g_dsurfedges[s->firstedge + i];
  186.                 if (e >= 0)
  187.                 {
  188.                     v = g_dvertexes + g_dedges[e].v[0];
  189.                 }
  190.                 else
  191.                 {
  192.                     v = g_dvertexes + g_dedges[-e].v[1];
  193.                 }
  194.                 VectorAdd(v->point, g_face_offset[facenum], v->point);
  195.                 Log("(%4.3f %4.3f %4.3f) ", v->point[0], v->point[1], v->point[2]);
  196.             }
  197.             Log("\n");
  198.  
  199.             Error( "Bad surface extents (%d x %d)\nCheck the file ZHLTProblems.html for a detailed explanation of this problem", l->texsize[0], l->texsize[1]);
  200.         }
  201.     }
  202. }
  203.  
  204. // =====================================================================================
  205. //  CalcFaceVectors
  206. //      Fills in texorg, worldtotex. and textoworld
  207. // =====================================================================================
  208. static void     CalcFaceVectors(lightinfo_t* l)
  209. {
  210.     texinfo_t*      tex;
  211.     int             i, j;
  212.     vec3_t          texnormal;
  213.     vec_t           distscale;
  214.     vec_t           dist, len;
  215.  
  216.     tex = &g_texinfo[l->face->texinfo];
  217.  
  218.     // convert from float to double
  219.     for (i = 0; i < 2; i++)
  220.     {
  221.         for (j = 0; j < 3; j++)
  222.         {
  223.             l->worldtotex[i][j] = tex->vecs[i][j];
  224.         }
  225.     }
  226.  
  227.     // calculate a normal to the texture axis.  points can be moved along this
  228.     // without changing their S/T
  229.     CrossProduct(tex->vecs[1], tex->vecs[0], texnormal);
  230.     VectorNormalize(texnormal);
  231.  
  232.     // flip it towards plane normal
  233.     distscale = DotProduct(texnormal, l->facenormal);
  234.     if (distscale == 0.0)
  235.     {
  236.         const unsigned facenum = l->face - g_dfaces;
  237.     
  238.         ThreadLock();
  239.         Log("Malformed face (%d) normal @ \n", facenum);
  240.         Winding* w = new Winding(*l->face);
  241.         {
  242.             const unsigned numpoints = w->m_NumPoints;
  243.             unsigned x;
  244.             for (x=0; x<numpoints; x++)
  245.             {
  246.                 VectorAdd(w->m_Points[x], g_face_offset[facenum], w->m_Points[x]);
  247.             }
  248.         }
  249.         w->Print();
  250.         delete w;
  251.         ThreadUnlock();
  252.  
  253.         hlassume(false, assume_MalformedTextureFace);
  254.     }
  255.  
  256.     if (distscale < 0)
  257.     {
  258.         distscale = -distscale;
  259.         VectorSubtract(vec3_origin, texnormal, texnormal);
  260.     }
  261.  
  262.     // distscale is the ratio of the distance along the texture normal to
  263.     // the distance along the plane normal
  264.     distscale = 1.0 / distscale;
  265.  
  266.     for (i = 0; i < 2; i++)
  267.     {
  268.         len = (float)VectorLength(l->worldtotex[i]);
  269.         dist = DotProduct(l->worldtotex[i], l->facenormal);
  270.         dist *= distscale;
  271.         VectorMA(l->worldtotex[i], -dist, texnormal, l->textoworld[i]);
  272.         VectorScale(l->textoworld[i], (1 / len) * (1 / len), l->textoworld[i]);
  273.     }
  274.  
  275.     // calculate texorg on the texture plane
  276.     for (i = 0; i < 3; i++)
  277.     {
  278.         l->texorg[i] = -tex->vecs[0][3] * l->textoworld[0][i] - tex->vecs[1][3] * l->textoworld[1][i];
  279.     }
  280.  
  281.     // project back to the face plane
  282.     dist = DotProduct(l->texorg, l->facenormal) - l->facedist - DEFAULT_HUNT_OFFSET;
  283.     dist *= distscale;
  284.     VectorMA(l->texorg, -dist, texnormal, l->texorg);
  285.  
  286. }
  287.  
  288. // =====================================================================================
  289. //  SetSurfFromST
  290. // =====================================================================================
  291. static void     SetSurfFromST(const lightinfo_t* const l, vec_t* surf, const vec_t s, const vec_t t)
  292. {
  293.     const int       facenum = l->surfnum;
  294.     int             j;
  295.  
  296.     for (j = 0; j < 3; j++)
  297.     {
  298.         surf[j] = l->texorg[j] + l->textoworld[0][j] * s + l->textoworld[1][j] * t;
  299.     }
  300.  
  301.     // Adjust for origin-based models
  302.     VectorAdd(surf, g_face_offset[facenum], surf);
  303. }
  304.  
  305. // =====================================================================================
  306. //  FindSurfaceMidpoint
  307. // =====================================================================================
  308. static dleaf_t* FindSurfaceMidpoint(const lightinfo_t* const l, vec_t* midpoint)
  309. {
  310.     int             s, t;
  311.     int             w, h;
  312.     vec_t           starts, startt;
  313.     vec_t           us, ut;
  314.  
  315.     vec3_t          broken_midpoint;
  316.     vec3_t          surface_midpoint;
  317.     int             inside_point_count;
  318.  
  319.     dleaf_t*        last_valid_leaf = NULL;
  320.     dleaf_t*        leaf_mid;
  321.  
  322.     const int       facenum = l->surfnum;
  323.     const dface_t*  f = g_dfaces + facenum;
  324.     const dplane_t* p = getPlaneFromFace(f);
  325.  
  326.     const vec_t*    face_delta = g_face_offset[facenum];
  327.  
  328.     h = l->texsize[1] + 1;
  329.     w = l->texsize[0] + 1;
  330.     starts = (float)l->texmins[0] * 16;
  331.     startt = (float)l->texmins[1] * 16;
  332.  
  333.     // General case
  334.     inside_point_count = 0;
  335.     VectorClear(surface_midpoint);
  336.     for (t = 0; t < h; t++)
  337.     {
  338.         for (s = 0; s < w; s++)
  339.         {
  340.             us = starts + s * TEXTURE_STEP;
  341.             ut = startt + t * TEXTURE_STEP;
  342.  
  343.             SetSurfFromST(l, midpoint, us, ut);
  344.             if ((leaf_mid = PointInLeaf(midpoint)) != g_dleafs)
  345.             {
  346.                 if ((leaf_mid->contents != CONTENTS_SKY) && (leaf_mid->contents != CONTENTS_SOLID))
  347.                 {
  348.                     last_valid_leaf = leaf_mid;
  349.                     inside_point_count++;
  350.                     VectorAdd(surface_midpoint, midpoint, surface_midpoint);
  351.                 }
  352.             }
  353.         }
  354.     }
  355.  
  356.     if (inside_point_count > 1)
  357.     {
  358.         vec_t           tmp = 1.0 / inside_point_count;
  359.  
  360.         VectorScale(surface_midpoint, tmp, midpoint);
  361.  
  362.         //Verbose("Trying general at (%4.3f %4.3f %4.3f) %d\n", surface_midpoint[0], surface_midpoint[1], surface_midpoint[2], inside_point_count);
  363.         if (
  364.             (leaf_mid =
  365.              HuntForWorld(midpoint, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET)))
  366.         {
  367.             //Verbose("general method succeeded at (%4.3f %4.3f %4.3f)\n", midpoint[0], midpoint[1], midpoint[2]);
  368.             return leaf_mid;
  369.         }
  370.         //Verbose("Tried general , failed at (%4.3f %4.3f %4.3f)\n", midpoint[0], midpoint[1], midpoint[2]);
  371.     }
  372.     else if (inside_point_count == 1)
  373.     {
  374.         //Verbose("Returning single point from general\n");
  375.         VectorCopy(surface_midpoint, midpoint);
  376.         return last_valid_leaf;
  377.     }
  378.     else
  379.     {
  380.         //Verbose("general failed (no points)\n");
  381.     }
  382.  
  383.     // Try harder
  384.     inside_point_count = 0;
  385.     VectorClear(surface_midpoint);
  386.     for (t = 0; t < h; t++)
  387.     {
  388.         for (s = 0; s < w; s++)
  389.         {
  390.             us = starts + s * TEXTURE_STEP;
  391.             ut = startt + t * TEXTURE_STEP;
  392.  
  393.             SetSurfFromST(l, midpoint, us, ut);
  394.             leaf_mid =
  395.                 HuntForWorld(midpoint, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET);
  396.             if (leaf_mid != g_dleafs)
  397.             {
  398.                 last_valid_leaf = leaf_mid;
  399.                 inside_point_count++;
  400.                 VectorAdd(surface_midpoint, midpoint, surface_midpoint);
  401.             }
  402.         }
  403.     }
  404.  
  405.     if (inside_point_count > 1)
  406.     {
  407.         vec_t           tmp = 1.0 / inside_point_count;
  408.  
  409.         VectorScale(surface_midpoint, tmp, midpoint);
  410.  
  411.         if (
  412.             (leaf_mid =
  413.              HuntForWorld(midpoint, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET)))
  414.         {
  415.             //Verbose("best method succeeded at (%4.3f %4.3f %4.3f)\n", midpoint[0], midpoint[1], midpoint[2]);
  416.             return leaf_mid;
  417.         }
  418.         //Verbose("Tried best, failed at (%4.3f %4.3f %4.3f)\n", midpoint[0], midpoint[1], midpoint[2]);
  419.     }
  420.     else if (inside_point_count == 1)
  421.     {
  422.         //Verbose("Returning single point from best\n");
  423.         VectorCopy(surface_midpoint, midpoint);
  424.         return last_valid_leaf;
  425.     }
  426.     else
  427.     {
  428.         //Verbose("best failed (no points)\n");
  429.     }
  430.  
  431.     // Original broken code
  432.     {
  433.         vec_t           mids = (l->exactmaxs[0] + l->exactmins[0]) / 2;
  434.         vec_t           midt = (l->exactmaxs[1] + l->exactmins[1]) / 2;
  435.  
  436.         SetSurfFromST(l, midpoint, mids, midt);
  437.  
  438.         if ((leaf_mid = PointInLeaf(midpoint)) != g_dleafs)
  439.         {
  440.             if ((leaf_mid->contents != CONTENTS_SKY) && (leaf_mid->contents != CONTENTS_SOLID))
  441.             {
  442.                 return leaf_mid;
  443.             }
  444.         }
  445.  
  446.         VectorCopy(midpoint, broken_midpoint);
  447.         //Verbose("Tried original method, failed at (%4.3f %4.3f %4.3f)\n", midpoint[0], midpoint[1], midpoint[2]);
  448.     }
  449.  
  450.     VectorCopy(broken_midpoint, midpoint);
  451.     return HuntForWorld(midpoint, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET);
  452. }
  453.  
  454. // =====================================================================================
  455. //  SimpleNudge
  456. //      Return vec_t in point only valid when function returns true
  457. //      Use negative scales to push away from center instead
  458. // =====================================================================================
  459. static bool     SimpleNudge(vec_t* const point, const lightinfo_t* const l, vec_t* const s, vec_t* const t, const vec_t delta)
  460. {
  461.     const int       facenum = l->surfnum;
  462.     const dface_t*  f = g_dfaces + facenum;
  463.     const dplane_t* p = getPlaneFromFace(f);
  464.     const vec_t*    face_delta = g_face_offset[facenum];
  465.     const int       h = l->texsize[1] + 1;
  466.     const int       w = l->texsize[0] + 1;
  467.     const vec_t     half_w = (vec_t)(w - 1) / 2.0;
  468.     const vec_t     half_h = (vec_t)(h - 1) / 2.0;
  469.     const vec_t     s_vec = *s;
  470.     const vec_t     t_vec = *t;
  471.     vec_t           s1;
  472.     vec_t           t1;
  473.  
  474.     if (s_vec > half_w)
  475.     {
  476.         s1 = s_vec - delta;
  477.     }
  478.     else
  479.     {
  480.         s1 = s_vec + delta;
  481.     }
  482.  
  483.     SetSurfFromST(l, point, s1, t_vec);
  484.     if (HuntForWorld(point, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET))
  485.     {
  486.         *s = s1;
  487.         return true;
  488.     }
  489.  
  490.     if (t_vec > half_h)
  491.     {
  492.         t1 = t_vec - delta;
  493.     }
  494.     else
  495.     {
  496.         t1 = t_vec + delta;
  497.     }
  498.  
  499.     SetSurfFromST(l, point, s_vec, t1);
  500.     if (HuntForWorld(point, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET))
  501.     {
  502.         *t = t1;
  503.         return true;
  504.     }
  505.  
  506.     return false;
  507. }
  508.  
  509. typedef enum
  510. {
  511.     LightOutside,                                          // Not lit
  512.     LightShifted,                                          // used HuntForWorld on 100% dark face
  513.     LightShiftedInside,                                    // moved to neighbhor on 2nd cleanup pass
  514.     LightNormal,                                           // Normally lit with no movement
  515.     LightPulledInside,                                     // Pulled inside by bleed code adjustments
  516.     LightSimpleNudge,                                      // A simple nudge 1/3 or 2/3 towards center along S or T axist
  517.     LightSimpleNudgeEmbedded                               // A nudge either 1 full unit in each of S and T axis, or 1/3 or 2/3 AWAY from center
  518. }
  519. light_flag_t;
  520.  
  521. // =====================================================================================
  522. //  CalcPoints
  523. //      For each texture aligned grid point, back project onto the plane
  524. //      to get the world xyz value of the sample point
  525. // =====================================================================================
  526. static void     CalcPoints(lightinfo_t* l)
  527. {
  528.     const int       facenum = l->surfnum;
  529.     const dface_t*  f = g_dfaces + facenum;
  530.     const dplane_t* p = getPlaneFromFace(f);
  531.  
  532.     const vec_t*    face_delta = g_face_offset[facenum];
  533.     const eModelLightmodes lightmode = g_face_lightmode[facenum];
  534.  
  535.     const vec_t     mids = (l->exactmaxs[0] + l->exactmins[0]) / 2;
  536.     const vec_t     midt = (l->exactmaxs[1] + l->exactmins[1]) / 2;
  537.  
  538.     const int       h = l->texsize[1] + 1;
  539.     const int       w = l->texsize[0] + 1;
  540.  
  541.     const vec_t     starts = (l->texmins[0] * 16);
  542.     const vec_t     startt = (l->texmins[1] * 16);
  543.  
  544.     light_flag_t    LuxelFlags[MAX_SINGLEMAP];
  545.     light_flag_t*   pLuxelFlags;
  546.     vec_t           us, ut;
  547.     vec_t*          surf;
  548.     vec3_t          surface_midpoint;
  549.     dleaf_t*        leaf_mid;
  550.     dleaf_t*        leaf_surf;
  551.     int             s, t;
  552.     int             i;
  553.  
  554.     l->numsurfpt = w * h;
  555.  
  556.     memset(LuxelFlags, 0, sizeof(LuxelFlags));
  557.  
  558.     leaf_mid = FindSurfaceMidpoint(l, surface_midpoint);
  559. #if 0
  560.     if (!leaf_mid)
  561.     {
  562.         Developer(DEVELOPER_LEVEL_FLUFF, "CalcPoints [face %d] (%4.3f %4.3f %4.3f) midpoint outside world\n",
  563.                   facenum, surface_midpoint[0], surface_midpoint[1], surface_midpoint[2]);
  564.     }
  565.     else
  566.     {
  567.         Developer(DEVELOPER_LEVEL_FLUFF, "FindSurfaceMidpoint [face %d] @ (%4.3f %4.3f %4.3f)\n",
  568.                   facenum, surface_midpoint[0], surface_midpoint[1], surface_midpoint[2]);
  569.     }
  570. #endif
  571.  
  572.     // First pass, light normally, and pull any faces toward the center for bleed adjustment
  573.  
  574.     surf = l->surfpt[0];
  575.     pLuxelFlags = LuxelFlags;
  576.     for (t = 0; t < h; t++)
  577.     {
  578.         for (s = 0; s < w; s++, surf += 3, pLuxelFlags++)
  579.         {
  580.             vec_t           original_s = us = starts + s * TEXTURE_STEP;
  581.             vec_t           original_t = ut = startt + t * TEXTURE_STEP;
  582.  
  583.             SetSurfFromST(l, surf, us, ut);
  584.             leaf_surf = HuntForWorld(surf, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET);
  585.  
  586.             if (!leaf_surf)
  587.             {
  588.                 // At first try a 1/3 and 2/3 distance to nearest in each S and T axis towards the face midpoint
  589.                 if (SimpleNudge(surf, l, &us, &ut, TEXTURE_STEP * (1.0 / 3.0)))
  590.                 {
  591.                     *pLuxelFlags = LightSimpleNudge;
  592.                 }
  593.                 else if (SimpleNudge(surf, l, &us, &ut, -TEXTURE_STEP * (1.0 / 3.0)))
  594.                 {
  595.                     *pLuxelFlags = LightSimpleNudge;
  596.                 }
  597.                 else if (SimpleNudge(surf, l, &us, &ut, TEXTURE_STEP * (2.0 / 3.0)))
  598.                 {
  599.                     *pLuxelFlags = LightSimpleNudge;
  600.                 }
  601.                 else if (SimpleNudge(surf, l, &us, &ut, -TEXTURE_STEP * (2.0 / 3.0)))
  602.                 {
  603.                     *pLuxelFlags = LightSimpleNudge;
  604.                 }
  605.                 // Next, if this is a model flagged with the 'Embedded' mode, try away from the facemid too
  606.                 else if (lightmode & eModelLightmodeEmbedded)
  607.                 {
  608.                     SetSurfFromST(l, surf, us, ut);
  609.                     if (SimpleNudge(surf, l, &us, &ut, TEXTURE_STEP))
  610.                     {
  611.                         *pLuxelFlags = LightSimpleNudgeEmbedded;
  612.                         continue;
  613.                     }
  614.                     if (SimpleNudge(surf, l, &us, &ut, -TEXTURE_STEP))
  615.                     {
  616.                         *pLuxelFlags = LightSimpleNudgeEmbedded;
  617.                         continue;
  618.                     }
  619.  
  620.                     SetSurfFromST(l, surf, original_s, original_t);
  621.                     *pLuxelFlags = LightOutside;
  622.                     continue;
  623.                 }
  624.             }
  625.  
  626.             if (!(lightmode & eModelLightmodeEmbedded))
  627.             {
  628.                 // Pull the sample points towards the facemid if visibility is blocked
  629.                 // and the facemid is inside the world
  630.                 int             nudge_divisor = max(max(w, h), 4);
  631.                 int             max_nudge = nudge_divisor + 1;
  632.                 bool            nudge_succeeded = false;
  633.  
  634.                 vec_t           nudge_s = (mids - us) / (vec_t)nudge_divisor;
  635.                 vec_t           nudge_t = (midt - ut) / (vec_t)nudge_divisor;
  636.  
  637.                 // if a line can be traced from surf to facemid, the point is good
  638.                 for (i = 0; i < max_nudge; i++)
  639.                 {
  640.                     // Make sure we are "in the world"(Not the zero leaf)
  641.                     if (leaf_mid)
  642.                     {
  643.                         SetSurfFromST(l, surf, us, ut);
  644.                         leaf_surf =
  645.                             HuntForWorld(surf, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE,
  646.                                          DEFAULT_HUNT_OFFSET);
  647.  
  648.                         if (leaf_surf)
  649.                         {
  650.                             if (TestLine(surface_midpoint, surf) == CONTENTS_EMPTY)
  651.                             {
  652.                                 if (lightmode & eModelLightmodeConcave)
  653.                                 {
  654. #ifdef HLRAD_HULLU
  655.                                     vec3_t transparency = { 1.0, 1.0, 1.0 };
  656.                                     if (TestSegmentAgainstOpaqueList(surface_midpoint, surf, transparency))
  657. #else
  658.                                     if (TestSegmentAgainstOpaqueList(surface_midpoint, surf))
  659. #endif
  660.                                     {
  661.                                         Log("SDF::4\n");
  662.                                         us += nudge_s;
  663.                                         ut += nudge_t;
  664.                                         continue;   // Try nudge again, we hit an opaque face
  665.                                     }
  666.                                 }
  667.                                 if (i)
  668.                                 {
  669.                                     *pLuxelFlags = LightPulledInside;
  670.                                 }
  671.                                 else
  672.                                 {
  673.                                     *pLuxelFlags = LightNormal;
  674.                                 }
  675.                                 nudge_succeeded = true;
  676.                                 break;
  677.                             }
  678.                         }
  679.                     }
  680.                     else
  681.                     {
  682.                         leaf_surf = PointInLeaf(surf);
  683.                         if (leaf_surf != g_dleafs)
  684.                         {
  685.                             if ((leaf_surf->contents != CONTENTS_SKY) && (leaf_surf->contents != CONTENTS_SOLID))
  686.                             {
  687.                                 *pLuxelFlags = LightNormal;
  688.                                 nudge_succeeded = true;
  689.                                 break;
  690.                             }
  691.                         }
  692.                     }
  693.  
  694.                     us += nudge_s;
  695.                     ut += nudge_t;
  696.                 }
  697.  
  698.                 if (!nudge_succeeded)
  699.                 {
  700.                     SetSurfFromST(l, surf, original_s, original_t);
  701.                     *pLuxelFlags = LightOutside;
  702.                 }
  703.             }
  704.         }
  705.     }
  706.  
  707.     // 2nd Pass, find units that are not lit and try to move them one half or unit worth 
  708.     // in each direction and see if that is lit.
  709.     // This handles 1 x N lightmaps which are all dark everywhere and have no frame of refernece
  710.     // for a good center or directly lit areas
  711.     surf = l->surfpt[0];
  712.     pLuxelFlags = LuxelFlags;
  713. #if 0
  714.     Developer(DEVELOPER_LEVEL_SPAM,
  715.               "w (%d) h (%d) dim (%d) leafmid (%4.3f %4.3f %4.3f) plane normal (%4.3f) (%4.3f) (%4.3f) dist (%f)\n", w,
  716.               h, w * h, surface_midpoint[0], surface_midpoint[1], surface_midpoint[2], p->normal[0], p->normal[1],
  717.               p->normal[2], p->dist);
  718. #endif
  719.     {
  720.         int             total_dark = 0;
  721.         int             total_adjusted = 0;
  722.  
  723.         for (t = 0; t < h; t++)
  724.         {
  725.             for (s = 0; s < w; s++, surf += 3, pLuxelFlags++)
  726.             {
  727.                 if (!*pLuxelFlags)
  728.                 {
  729. #if 0
  730.                     Developer(DEVELOPER_LEVEL_FLUFF, "Dark (%d %d) (%4.3f %4.3f %4.3f)\n",
  731.                               s, t, surf[0], surf[1], surf[2]);
  732. #endif
  733.                     total_dark++;
  734.                     if (HuntForWorld(surf, face_delta, p, DEFAULT_HUNT_SIZE, DEFAULT_HUNT_SCALE, DEFAULT_HUNT_OFFSET))
  735.                     {
  736. #if 0
  737.                         Developer(DEVELOPER_LEVEL_FLUFF, "Shifted %d %d to (%4.3f %4.3f %4.3f)\n", s, t, surf[0],
  738.                                   surf[1], surf[2]);
  739. #endif
  740.                         *pLuxelFlags = LightShifted;
  741.                         total_adjusted++;
  742.                     }
  743.                     else if (HuntForWorld(surf, face_delta, p, 101, 0.5, DEFAULT_HUNT_OFFSET))
  744.                     {
  745. #if 0
  746.                         Developer(DEVELOPER_LEVEL_FLUFF, "Shifted %d %d to (%4.3f %4.3f %4.3f)\n", s, t, surf[0],
  747.                                   surf[1], surf[2]);
  748. #endif
  749.                         *pLuxelFlags = LightShifted;
  750.                         total_adjusted++;
  751.                     }
  752.                 }
  753.             }
  754.         }
  755. #if 0
  756.         if (total_dark)
  757.         {
  758.             Developer(DEVELOPER_LEVEL_FLUFF, "Pass 2 : %d dark, %d corrected\n", total_dark, total_adjusted);
  759.         }
  760. #endif
  761.     }
  762.  
  763.     // 3rd Pass, find units that are not lit and move them towards neighbhors who are
  764.     // Currently finds the first lit neighbhor and uses its data
  765.     surf = l->surfpt[0];
  766.     pLuxelFlags = LuxelFlags;
  767.     {
  768.         int             total_dark = 0;
  769.         int             total_adjusted = 0;
  770.  
  771.         for (t = 0; t < h; t++)
  772.         {
  773.             for (s = 0; s < w; s++, surf += 3, pLuxelFlags++)
  774.             {
  775.                 if (!*pLuxelFlags)
  776.                 {
  777.                     int             x_min = max(0, s - 1);
  778.                     int             x_max = min(w, s + 1);
  779.                     int             y_min = max(0, t - 1);
  780.                     int             y_max = min(t, t + 1);
  781.  
  782.                     int             x, y;
  783.  
  784. #if 0
  785.                     Developer(DEVELOPER_LEVEL_FLUFF, "Point outside (%d %d) (%4.3f %4.3f %4.3f)\n",
  786.                               s, t, surf[0], surf[1], surf[2]);
  787. #endif
  788.  
  789.                     total_dark++;
  790.  
  791.                     for (x = x_min; x < x_max; x++)
  792.                     {
  793.                         for (y = y_min; y < y_max; y++)
  794.                         {
  795.                             if (*pLuxelFlags >= LightNormal)
  796.                             {
  797.                                 dleaf_t*        leaf;
  798.                                 vec_t*          other_surf = l->surfpt[0];
  799.  
  800.                                 other_surf += ((y * w) + x) * 3;
  801.  
  802.                                 leaf = PointInLeaf(other_surf);
  803.                                 if ((leaf->contents != CONTENTS_SKY && leaf->contents != CONTENTS_SOLID))
  804.                                 {
  805.                                     *pLuxelFlags = LightShiftedInside;
  806. #if 0
  807.                                     Developer(DEVELOPER_LEVEL_MESSAGE,
  808.                                               "Nudged (%d %d) (%4.3f %4.3f %4.3f) to (%d %d) (%4.3f %4.3f %4.3f) \n",
  809.                                               s, t, surf[0], surf[1], surf[2], x, y, other_surf[0], other_surf[1],
  810.                                               other_surf[2]);
  811. #endif
  812.                                     VectorCopy(other_surf, surf);
  813.                                     total_adjusted++;
  814.                                     goto found_it;
  815.                                 }
  816.                             }
  817.                         }
  818.                     }
  819.                 }
  820.               found_it:;
  821.             }
  822.         }
  823. #if 0
  824.         if (total_dark)
  825.         {
  826.             Developer(DEVELOPER_LEVEL_FLUFF, "Pass 2 : %d dark, %d corrected\n", total_dark, total_adjusted);
  827.         }
  828. #endif
  829.     }
  830. }
  831.  
  832. //==============================================================
  833.  
  834. typedef struct
  835. {
  836.     vec3_t          pos;
  837.     vec3_t          light;
  838. }
  839. sample_t;
  840.  
  841. typedef struct
  842. {
  843.     int             numsamples;
  844.     sample_t*       samples[MAXLIGHTMAPS];
  845. }
  846. facelight_t;
  847.  
  848. static directlight_t* directlights[MAX_MAP_LEAFS];
  849. static facelight_t facelight[MAX_MAP_FACES];
  850. static int      numdlights;
  851.  
  852. #define    DIRECT_SCALE    0.1f
  853.  
  854. // =====================================================================================
  855. //  CreateDirectLights
  856. // =====================================================================================
  857. void            CreateDirectLights()
  858. {
  859.     unsigned        i;
  860.     patch_t*        p;
  861.     directlight_t*  dl;
  862.     dleaf_t*        leaf;
  863.     int             leafnum;
  864.     entity_t*       e;
  865.     entity_t*       e2;
  866.     const char*     name;
  867.     const char*     target;
  868.     float           angle;
  869.     vec3_t          dest;
  870.  
  871.     // AJM: coplaner lighting
  872.     vec3_t          temp_normal;
  873.  
  874.     numdlights = 0;
  875.  
  876.     //
  877.     // surfaces
  878.     //
  879.     for (i = 0, p = g_patches; i < g_num_patches; i++, p++)
  880.     {
  881. #ifdef ZHLT_TEXLIGHT
  882.         if (VectorAvg(p->baselight) >= g_dlight_threshold) //LRC
  883. #else
  884.         if (VectorAvg(p->totallight) >= g_dlight_threshold)
  885. #endif
  886.         {
  887.             numdlights++;
  888.             dl = (directlight_t*)calloc(1, sizeof(directlight_t));
  889.  
  890.             VectorCopy(p->origin, dl->origin);
  891.  
  892.             leaf = PointInLeaf(dl->origin);
  893.             leafnum = leaf - g_dleafs;
  894.  
  895.             dl->next = directlights[leafnum];
  896.             directlights[leafnum] = dl;
  897. #ifdef ZHLT_TEXLIGHT
  898.             dl->style = p->emitstyle; //LRC
  899. #endif
  900.  
  901.             dl->type = emit_surface;
  902.             VectorCopy(getPlaneFromFaceNumber(p->faceNumber)->normal, dl->normal);
  903. #ifdef ZHLT_TEXLIGHT
  904.             VectorCopy(p->baselight, dl->intensity); //LRC
  905. #else
  906.             VectorCopy(p->totallight, dl->intensity);
  907. #endif
  908.             VectorScale(dl->intensity, p->area, dl->intensity);
  909.             VectorScale(dl->intensity, DIRECT_SCALE, dl->intensity);
  910.         
  911.             // --------------------------------------------------------------
  912.             // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  913.             // mazemaster's l33t backwards lighting (I still haven't a clue
  914.             // what it's supposed to be for) :-)
  915. #ifdef HLRAD_WHOME
  916.  
  917.             if (g_softlight_hack[0] || g_softlight_hack[1] || g_softlight_hack[2]) 
  918.             {
  919.                 numdlights++;
  920.                 dl = (directlight_t *) calloc(1, sizeof(directlight_t));
  921.  
  922.                 VectorCopy(p->origin, dl->origin);
  923.  
  924.                 leaf = PointInLeaf(dl->origin);
  925.                 leafnum = leaf - g_dleafs;
  926.  
  927.                 dl->next = directlights[leafnum];
  928.                 directlights[leafnum] = dl;
  929.  
  930.                 dl->type = emit_surface;
  931.                 VectorCopy(getPlaneFromFaceNumber(p->faceNumber)->normal, dl->normal);
  932.                 VectorScale(dl->normal, g_softlight_hack_distance, temp_normal);
  933.                 VectorAdd(dl->origin, temp_normal, dl->origin);
  934.                 VectorScale(dl->normal, -1, dl->normal);
  935.  
  936. #ifdef ZHLT_TEXLIGHT
  937.                 VectorCopy(p->baselight, dl->intensity); //LRC
  938. #else
  939.                 VectorCopy(p->totallight, dl->intensity);
  940. #endif
  941.                 VectorScale(dl->intensity, p->area, dl->intensity);
  942.                 VectorScale(dl->intensity, DIRECT_SCALE, dl->intensity);
  943.  
  944.                 dl->intensity[0] *= g_softlight_hack[0];
  945.                 dl->intensity[1] *= g_softlight_hack[1];
  946.                 dl->intensity[2] *= g_softlight_hack[2];
  947.             }
  948.  
  949. #endif
  950.             // --------------------------------------------------------------
  951.         }
  952.  
  953. #ifdef ZHLT_TEXLIGHT
  954.         //LRC        VectorClear(p->totallight[0]);
  955. #else
  956.         VectorClear(p->totallight);
  957. #endif
  958.     }
  959.  
  960.     //
  961.     // entities
  962.     //
  963.     for (i = 0; i < (unsigned)g_numentities; i++)
  964.     {
  965.         const char*     pLight;
  966.         double          r, g, b, scaler;
  967.         float           l1;
  968.         int             argCnt;
  969.  
  970.         e = &g_entities[i];
  971.         name = ValueForKey(e, "classname");
  972.         if (strncmp(name, "light", 5))
  973.             continue;
  974.  
  975.         numdlights++;
  976.         dl = (directlight_t*)calloc(1, sizeof(directlight_t));
  977.  
  978.         GetVectorForKey(e, "origin", dl->origin);
  979.  
  980.         leaf = PointInLeaf(dl->origin);
  981.         leafnum = leaf - g_dleafs;
  982.  
  983.         dl->next = directlights[leafnum];
  984.         directlights[leafnum] = dl;
  985.  
  986.         dl->style = IntForKey(e, "style");
  987. #ifdef ZHLT_TEXLIGHT
  988.         if (dl->style < 0) 
  989.             dl->style = -dl->style; //LRC
  990. #endif
  991.  
  992.         pLight = ValueForKey(e, "_light");
  993.         // scanf into doubles, then assign, so it is vec_t size independent
  994.         r = g = b = scaler = 0;
  995.         argCnt = sscanf(pLight, "%lf %lf %lf %lf", &r, &g, &b, &scaler);
  996.         dl->intensity[0] = (float)r;
  997.         if (argCnt == 1)
  998.         {
  999.             // The R,G,B values are all equal.
  1000.             dl->intensity[1] = dl->intensity[2] = (float)r;
  1001.         }
  1002.         else if (argCnt == 3 || argCnt == 4)
  1003.         {
  1004.             // Save the other two G,B values.
  1005.             dl->intensity[1] = (float)g;
  1006.             dl->intensity[2] = (float)b;
  1007.  
  1008.             // Did we also get an "intensity" scaler value too?
  1009.             if (argCnt == 4)
  1010.             {
  1011.                 // Scale the normalized 0-255 R,G,B values by the intensity scaler
  1012.                 dl->intensity[0] = dl->intensity[0] / 255 * (float)scaler;
  1013.                 dl->intensity[1] = dl->intensity[1] / 255 * (float)scaler;
  1014.                 dl->intensity[2] = dl->intensity[2] / 255 * (float)scaler;
  1015.             }
  1016.         }
  1017.         else
  1018.         {
  1019.             Log("light at (%f,%f,%f) has bad or missing '_light' value : '%s'\n",
  1020.                 dl->origin[0], dl->origin[1], dl->origin[2], pLight);
  1021.             continue;
  1022.         }
  1023.  
  1024.         dl->fade = FloatForKey(e, "_fade");
  1025.         if (dl->fade == 0.0)
  1026.         {
  1027.             dl->fade = g_fade;
  1028.         }
  1029.  
  1030.         dl->falloff = IntForKey(e, "_falloff");
  1031.         if (dl->falloff == 0)
  1032.         {
  1033.             dl->falloff = g_falloff;
  1034.         }
  1035.  
  1036.         target = ValueForKey(e, "target");
  1037.  
  1038.         if (!strcmp(name, "light_spot") || !strcmp(name, "light_environment") || target[0])
  1039.         {
  1040.             if (!VectorAvg(dl->intensity))
  1041.             {
  1042.                 VectorFill(dl->intensity, 500);
  1043.             }
  1044.             dl->type = emit_spotlight;
  1045.             dl->stopdot = FloatForKey(e, "_cone");
  1046.             if (!dl->stopdot)
  1047.             {
  1048.                 dl->stopdot = 10;
  1049.             }
  1050.             dl->stopdot2 = FloatForKey(e, "_cone2");
  1051.             if (!dl->stopdot2)
  1052.             {
  1053.                 dl->stopdot2 = dl->stopdot;
  1054.             }
  1055.             if (dl->stopdot2 < dl->stopdot)
  1056.             {
  1057.                 dl->stopdot2 = dl->stopdot;
  1058.             }
  1059.             dl->stopdot2 = (float)cos(dl->stopdot2 / 180 * Q_PI);
  1060.             dl->stopdot = (float)cos(dl->stopdot / 180 * Q_PI);
  1061.  
  1062.             if (target[0])
  1063.             {                                              // point towards target
  1064.                 e2 = FindTargetEntity(target);
  1065.                 if (!e2)
  1066.                 {
  1067.                     Warning("light at (%i %i %i) has missing target",
  1068.                             (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]);
  1069.                 }
  1070.                 else
  1071.                 {
  1072.                     GetVectorForKey(e2, "origin", dest);
  1073.                     VectorSubtract(dest, dl->origin, dl->normal);
  1074.                     VectorNormalize(dl->normal);
  1075.                 }
  1076.             }
  1077.             else
  1078.             {                                              // point down angle
  1079.                 vec3_t          vAngles;
  1080.  
  1081.                 GetVectorForKey(e, "angles", vAngles);
  1082.  
  1083.                 angle = (float)FloatForKey(e, "angle");
  1084.                 if (angle == ANGLE_UP)
  1085.                 {
  1086.                     dl->normal[0] = dl->normal[1] = 0;
  1087.                     dl->normal[2] = 1;
  1088.                 }
  1089.                 else if (angle == ANGLE_DOWN)
  1090.                 {
  1091.                     dl->normal[0] = dl->normal[1] = 0;
  1092.                     dl->normal[2] = -1;
  1093.                 }
  1094.                 else
  1095.                 {
  1096.                     // if we don't have a specific "angle" use the "angles" YAW
  1097.                     if (!angle)
  1098.                     {
  1099.                         angle = vAngles[1];
  1100.                     }
  1101.  
  1102.                     dl->normal[2] = 0;
  1103.                     dl->normal[0] = (float)cos(angle / 180 * Q_PI);
  1104.                     dl->normal[1] = (float)sin(angle / 180 * Q_PI);
  1105.                 }
  1106.  
  1107.                 angle = FloatForKey(e, "pitch");
  1108.                 if (!angle)
  1109.                 {
  1110.                     // if we don't have a specific "pitch" use the "angles" PITCH
  1111.                     angle = vAngles[0];
  1112.                 }
  1113.  
  1114.                 dl->normal[2] = (float)sin(angle / 180 * Q_PI);
  1115.                 dl->normal[0] *= (float)cos(angle / 180 * Q_PI);
  1116.                 dl->normal[1] *= (float)cos(angle / 180 * Q_PI);
  1117.             }
  1118.  
  1119.             if (FloatForKey(e, "_sky") || !strcmp(name, "light_environment"))
  1120.             {
  1121.                 // -----------------------------------------------------------------------------------
  1122.                 // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  1123.                 // diffuse lighting hack - most of the following code nicked from earlier
  1124.                 // need to get diffuse intensity from new _diffuse_light key
  1125.                 //
  1126.                 // What does _sky do for spotlights, anyway?
  1127.                 // -----------------------------------------------------------------------------------
  1128. #ifdef HLRAD_WHOME
  1129.                 pLight = ValueForKey(e, "_diffuse_light");
  1130.                 r = g = b = scaler = 0;
  1131.                 argCnt = sscanf(pLight, "%lf %lf %lf %lf", &r, &g, &b, &scaler);
  1132.                 dl->diffuse_intensity[0] = (float)r;
  1133.                 if (argCnt == 1)
  1134.                 {
  1135.                     // The R,G,B values are all equal.
  1136.                     dl->diffuse_intensity[1] = dl->diffuse_intensity[2] = (float)r;
  1137.                 }
  1138.                 else if (argCnt == 3 || argCnt == 4)
  1139.                 {
  1140.                     // Save the other two G,B values.
  1141.                     dl->diffuse_intensity[1] = (float)g;
  1142.                     dl->diffuse_intensity[2] = (float)b;
  1143.  
  1144.                     // Did we also get an "intensity" scaler value too?
  1145.                       if (argCnt == 4)
  1146.                         {
  1147.                         // Scale the normalized 0-255 R,G,B values by the intensity scaler
  1148.                         dl->diffuse_intensity[0] = dl->diffuse_intensity[0] / 255 * (float)scaler;
  1149.                         dl->diffuse_intensity[1] = dl->diffuse_intensity[1] / 255 * (float)scaler;
  1150.                         dl->diffuse_intensity[2] = dl->diffuse_intensity[2] / 255 * (float)scaler;
  1151.                     }
  1152.                 }
  1153.                 else
  1154.                 {
  1155.                     // backwards compatibility with maps without _diffuse_light
  1156.  
  1157.                     dl->diffuse_intensity[0] = dl->intensity[0];
  1158.                     dl->diffuse_intensity[1] = dl->intensity[1];
  1159.                     dl->diffuse_intensity[2] = dl->intensity[2];
  1160.                 }
  1161. #endif
  1162.                 // -----------------------------------------------------------------------------------
  1163.  
  1164.                 dl->type = emit_skylight;
  1165.                 dl->stopdot2 = FloatForKey(e, "_sky");     // hack stopdot2 to a sky key number
  1166.             }
  1167.         }
  1168.         else
  1169.         {
  1170.             if (!VectorAvg(dl->intensity))
  1171.                 VectorFill(dl->intensity, 300);
  1172.             dl->type = emit_point;
  1173.         }
  1174.  
  1175.         if (dl->type != emit_skylight)
  1176.         {
  1177.             l1 = max(dl->intensity[0], max(dl->intensity[1], dl->intensity[2]));
  1178.             l1 = l1 * l1 / 10;
  1179.  
  1180.             dl->intensity[0] *= l1;
  1181.             dl->intensity[1] *= l1;
  1182.             dl->intensity[2] *= l1;
  1183.         }
  1184.     }
  1185.  
  1186.     hlassume(numdlights, assume_NoLights);
  1187.     Log("%i direct lights\n", numdlights);
  1188. }
  1189.  
  1190. // =====================================================================================
  1191. //  DeleteDirectLights
  1192. // =====================================================================================
  1193. void            DeleteDirectLights()
  1194. {
  1195.     int             l;
  1196.     directlight_t*  dl;
  1197.  
  1198.     for (l = 0; l < g_numleafs; l++)
  1199.     {
  1200.         dl = directlights[l];
  1201.         while (dl)
  1202.         {
  1203.             directlights[l] = dl->next;
  1204.             free(dl);
  1205.             dl = directlights[l];
  1206.         }
  1207.     }
  1208.  
  1209.     // AJM: todo: strip light entities out at this point
  1210. }
  1211.  
  1212. // =====================================================================================
  1213. //  GatherSampleLight
  1214. // =====================================================================================
  1215. #define NUMVERTEXNORMALS    162
  1216. double          r_avertexnormals[NUMVERTEXNORMALS][3] = {
  1217. #include "../common/anorms.h"
  1218. };
  1219. static void     GatherSampleLight(const vec3_t pos, const byte* const pvs, const vec3_t normal, vec3_t* sample, byte* styles)
  1220. {
  1221.     int             i;
  1222.     directlight_t*  l;
  1223.     vec3_t          add;
  1224.     vec3_t          delta;
  1225.     float           dot, dot2;
  1226.     float           dist;
  1227.     float           ratio;
  1228. #ifdef HLRAD_OPACITY // AJM
  1229.     float           l_opacity;
  1230. #endif
  1231.     int             style_index;
  1232.     directlight_t*  sky_used = NULL;
  1233.  
  1234.     for (i = 1; i < g_numleafs; i++)
  1235.     {
  1236.         l = directlights[i];
  1237.         if (l)
  1238.         {
  1239.             if (((l->type == emit_skylight) && (g_sky_lighting_fix)) || (pvs[(i - 1) >> 3] & (1 << ((i - 1) & 7))))
  1240.             {
  1241.                 for (; l; l = l->next)
  1242.                 {
  1243.                     // skylights work fundamentally differently than normal lights
  1244.                     if (l->type == emit_skylight)
  1245.                     {
  1246.                         // only allow one of each sky type to hit any given point
  1247.                         if (sky_used)
  1248.                         {
  1249.                             continue;
  1250.                         }
  1251.                         sky_used = l;
  1252.  
  1253.                         // make sure the angle is okay
  1254.                         dot = -DotProduct(normal, l->normal);
  1255.                         if (dot <= ON_EPSILON / 10)
  1256.                         {
  1257.                             continue;
  1258.                         }
  1259.  
  1260.                         // search back to see if we can hit a sky brush
  1261.                         VectorScale(l->normal, -10000, delta);
  1262.                         VectorAdd(pos, delta, delta);
  1263.                         if (TestLine(pos, delta) != CONTENTS_SKY)
  1264.                         {
  1265.                             continue;                      // occluded
  1266.                         }
  1267.  
  1268. #ifdef HLRAD_HULLU
  1269.                         vec3_t transparency = {1.0,1.0,1.0};
  1270.                         if (TestSegmentAgainstOpaqueList(pos, delta, transparency))
  1271. #else
  1272.                         if (TestSegmentAgainstOpaqueList(pos, delta))
  1273. #endif                  
  1274.                         {
  1275.                             continue;
  1276.                         }
  1277.  
  1278.                         VectorScale(l->intensity, dot, add);
  1279. #ifdef HLRAD_HULLU
  1280.                         VectorMultiply(add, transparency, add);
  1281. #endif
  1282.  
  1283.                     }
  1284.                     else
  1285.                     {
  1286.                         float           denominator;
  1287.  
  1288.                         VectorSubtract(l->origin, pos, delta);
  1289.                         dist = VectorNormalize(delta);
  1290.                         dot = DotProduct(delta, normal);
  1291.                         //                        if (dot <= 0.0)
  1292.                         //                            continue;
  1293.                         if (dot <= ON_EPSILON / 10)
  1294.                         {
  1295.                             continue;                      // behind sample surface
  1296.                         }
  1297.  
  1298.                         if (dist < 1.0)
  1299.                         {
  1300.                             dist = 1.0;
  1301.                         }
  1302.  
  1303.                         // Variable power falloff (1 = inverse linear, 2 = inverse square
  1304.                         denominator = dist * l->fade;
  1305.                         if (l->falloff == 2)
  1306.                         {
  1307.                             denominator *= dist;
  1308.                         }
  1309.  
  1310.                         switch (l->type)
  1311.                         {
  1312.                         case emit_point:
  1313.                         {
  1314.                             // Variable power falloff (1 = inverse linear, 2 = inverse square
  1315.                             vec_t           denominator = dist * l->fade;
  1316.  
  1317.                             if (l->falloff == 2)
  1318.                             {
  1319.                                 denominator *= dist;
  1320.                             }
  1321.                             ratio = dot / denominator;
  1322.                             VectorScale(l->intensity, ratio, add);
  1323.                             break;
  1324.                         }
  1325.  
  1326.                         case emit_surface:
  1327.                         {
  1328.                             dot2 = -DotProduct(delta, l->normal);
  1329.                             if (dot2 <= ON_EPSILON / 10)
  1330.                             {
  1331.                                 continue;                  // behind light surface
  1332.                             }
  1333.  
  1334.                             // Variable power falloff (1 = inverse linear, 2 = inverse square
  1335.                             vec_t           denominator = dist * g_fade;
  1336.                             if (g_falloff == 2)
  1337.                             {
  1338.                                 denominator *= dist;
  1339.                             }
  1340.                             ratio = dot * dot2 / denominator;
  1341.  
  1342.                             VectorScale(l->intensity, ratio, add);
  1343.                             break;
  1344.                         }
  1345.  
  1346.                         case emit_spotlight:
  1347.                         {
  1348.                             dot2 = -DotProduct(delta, l->normal);
  1349.                             if (dot2 <= l->stopdot2)
  1350.                             {
  1351.                                 continue;                  // outside light cone
  1352.                             }
  1353.  
  1354.                             // Variable power falloff (1 = inverse linear, 2 = inverse square
  1355.                             vec_t           denominator = dist * l->fade;
  1356.                             if (l->falloff == 2)
  1357.                             {
  1358.                                 denominator *= dist;
  1359.                             }
  1360.                             ratio = dot * dot2 / denominator;
  1361.  
  1362.                             if (dot2 <= l->stopdot)
  1363.                             {
  1364.                                 ratio *= (dot2 - l->stopdot2) / (l->stopdot - l->stopdot2);
  1365.                             }
  1366.                             VectorScale(l->intensity, ratio, add);
  1367.                             break;
  1368.                         }
  1369.  
  1370.                         default:
  1371.                         {
  1372.                             hlassume(false, assume_BadLightType);
  1373.                             break;
  1374.                         }
  1375.                         }
  1376.                     }
  1377.  
  1378.                     if (VectorMaximum(add) > (l->style ? g_coring : 0))
  1379.                     {
  1380. #ifdef HLRAD_HULLU
  1381.                          vec3_t transparency = {1.0,1.0,1.0};
  1382. #endif 
  1383.  
  1384.                         if (l->type != emit_skylight && TestLine(pos, l->origin) != CONTENTS_EMPTY)
  1385.                         {
  1386.                             continue;                      // occluded
  1387.                         }
  1388.  
  1389.                         if (l->type != emit_skylight)
  1390.                         {                                  // Don't test from light_environment entities to face, the special sky code occludes correctly
  1391. #ifdef HLRAD_HULLU
  1392.                             if (TestSegmentAgainstOpaqueList(pos, l->origin, transparency))
  1393. #else
  1394.                             if (TestSegmentAgainstOpaqueList(pos, l->origin))
  1395. #endif
  1396.                             {
  1397.                                 continue;
  1398.                             }
  1399.                         }
  1400.  
  1401. #ifdef HLRAD_OPACITY
  1402.                         //VectorScale(add, l_opacity, add);
  1403. #endif
  1404.  
  1405.                         for (style_index = 0; style_index < MAXLIGHTMAPS; style_index++)
  1406.                         {
  1407.                             if (styles[style_index] == l->style || styles[style_index] == 255)
  1408.                             {
  1409.                                 break;
  1410.                             }
  1411.                         }
  1412.  
  1413.                         if (style_index == MAXLIGHTMAPS)
  1414.                         {
  1415.                             Warning("Too many direct light styles on a face(%f,%f,%f)", pos[0], pos[1], pos[2]);
  1416.                             continue;
  1417.                         }
  1418.  
  1419.                         if (styles[style_index] == 255)
  1420.                         {
  1421.                             styles[style_index] = l->style;
  1422.                         }
  1423.  
  1424. #ifdef HLRAD_HULLU
  1425.                         VectorMultiply(add,transparency,add);
  1426. #endif
  1427.                         VectorAdd(sample[style_index], add, sample[style_index]);
  1428.                     }
  1429.                 }
  1430.             }
  1431.         }
  1432.     }
  1433.  
  1434.     if (sky_used && g_indirect_sun != 0.0)
  1435.     {
  1436.         vec3_t          total;
  1437.         int             j;
  1438.         vec3_t          sky_intensity;
  1439.  
  1440.         // -----------------------------------------------------------------------------------
  1441.         // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  1442.         // Instead of using intensity from sky_used->intensity, get it from the new sky_used->diffuse_intensity
  1443. #ifdef HLRAD_WHOME
  1444.         VectorScale(sky_used->diffuse_intensity, g_indirect_sun / (NUMVERTEXNORMALS * 2), sky_intensity);
  1445. #else
  1446.         VectorScale(sky_used->intensity, g_indirect_sun / (NUMVERTEXNORMALS * 2), sky_intensity);
  1447. #endif
  1448.         // That should be it. Who knows - it might actually work!
  1449.         // AJM: It DOES actually work. Havent you ever heard of beta testing....
  1450.         // -----------------------------------------------------------------------------------
  1451.  
  1452.         total[0] = total[1] = total[2] = 0.0;
  1453.         for (j = 0; j < NUMVERTEXNORMALS; j++)
  1454.         {
  1455.             // make sure the angle is okay
  1456.             dot = -DotProduct(normal, r_avertexnormals[j]);
  1457.             if (dot <= ON_EPSILON / 10)
  1458.             {
  1459.                 continue;
  1460.             }
  1461.  
  1462.             // search back to see if we can hit a sky brush
  1463.             VectorScale(r_avertexnormals[j], -10000, delta);
  1464.             VectorAdd(pos, delta, delta);
  1465.             if (TestLine(pos, delta) != CONTENTS_SKY)
  1466.             {
  1467.                 continue;                                  // occluded
  1468.             }
  1469.  
  1470.             VectorScale(sky_intensity, dot, add);
  1471.             VectorAdd(total, add, total);
  1472.         }
  1473.         if (VectorMaximum(total) > 0)
  1474.         {
  1475.             for (style_index = 0; style_index < MAXLIGHTMAPS; style_index++)
  1476.             {
  1477.                 if (styles[style_index] == sky_used->style || styles[style_index] == 255)
  1478.                 {
  1479.                     break;
  1480.                 }
  1481.             }
  1482.  
  1483.             if (style_index == MAXLIGHTMAPS)
  1484.             {
  1485.                 Warning("Too many direct light styles on a face(%f,%f,%f)\n", pos[0], pos[1], pos[2]);
  1486.                 return;
  1487.             }
  1488.  
  1489.             if (styles[style_index] == 255)
  1490.             {
  1491.                 styles[style_index] = sky_used->style;
  1492.             }
  1493.  
  1494.             VectorAdd(sample[style_index], total, sample[style_index]);
  1495.         }
  1496.     }
  1497. }
  1498.  
  1499. // =====================================================================================
  1500. //  AddSampleToPatch
  1501. //      Take the sample's collected light and add it back into the apropriate patch for the radiosity pass.
  1502. // =====================================================================================
  1503. #ifdef ZHLT_TEXLIGHT
  1504. static void     AddSampleToPatch(const sample_t* const s, const int facenum, int style) //LRC
  1505. #else
  1506. static void     AddSampleToPatch(const sample_t* const s, const int facenum)
  1507. #endif
  1508. {
  1509.     patch_t*        patch;
  1510.     BoundingBox     bounds;
  1511.     int             i;
  1512.  
  1513.     if (g_numbounce == 0)
  1514.     {
  1515.         return;
  1516.     }
  1517.  
  1518.     for (patch = g_face_patches[facenum]; patch; patch = patch->next)
  1519.     {
  1520.         // see if the point is in this patch (roughly)
  1521.         patch->winding->getBounds(bounds);
  1522.         for (i = 0; i < 3; i++)
  1523.         {
  1524.             if (bounds.m_Mins[i] > s->pos[i] + 16)
  1525.             {
  1526.                 goto nextpatch;
  1527.             }
  1528.             if (bounds.m_Maxs[i] < s->pos[i] - 16)
  1529.             {
  1530.                 goto nextpatch;
  1531.             }
  1532.         }
  1533.  
  1534.         // add the sample to the patch
  1535. #ifdef ZHLT_TEXLIGHT
  1536.         //LRC:
  1537.         for (i = 0; i < MAXLIGHTMAPS && patch->totalstyle[i] != 255; i++)
  1538.         {
  1539.             if (patch->totalstyle[i] == style)
  1540.                 break;
  1541.         }
  1542.         if (i == MAXLIGHTMAPS)
  1543.         {
  1544.             Warning("Too many direct light styles on a face(?,?,?)\n");
  1545.         }
  1546.         else
  1547.         {
  1548.             if (patch->totalstyle[i] == 255)
  1549.             {
  1550.                 patch->totalstyle[i] = style;
  1551.             }
  1552.  
  1553.             patch->samples[i]++;
  1554.             VectorAdd(patch->samplelight[i], s->light, patch->samplelight[i]);
  1555.         }
  1556.         //LRC (ends)
  1557. #else
  1558.         patch->samples++;
  1559.         VectorAdd(patch->samplelight, s->light, patch->samplelight);
  1560. #endif
  1561.         //return;
  1562.  
  1563.       nextpatch:;
  1564.     }
  1565.  
  1566.     // don't worry if some samples don't find a patch
  1567. }
  1568.  
  1569. // =====================================================================================
  1570. //  GetPhongNormal
  1571. // =====================================================================================
  1572. void            GetPhongNormal(int facenum, vec3_t spot, vec3_t phongnormal)
  1573. {
  1574.     int             j;
  1575.     const dface_t*  f = g_dfaces + facenum;
  1576.     const dplane_t* p = getPlaneFromFace(f);
  1577.     vec3_t          facenormal;
  1578.  
  1579.     VectorCopy(p->normal, facenormal);
  1580.     VectorCopy(facenormal, phongnormal);
  1581.  
  1582.     if (g_smoothing_threshold > 0.0)
  1583.     {
  1584.         // Calculate modified point normal for surface
  1585.         // Use the edge normals iff they are defined.  Bend the surface towards the edge normal(s)
  1586.         // Crude first attempt: find nearest edge normal and do a simple interpolation with facenormal.
  1587.         // Second attempt: find edge points+center that bound the point and do a three-point triangulation(baricentric)
  1588.         // Better third attempt: generate the point normals for all vertices and do baricentric triangulation.
  1589.  
  1590.         for (j = 0; j < f->numedges; j++)
  1591.         {
  1592.             vec3_t          p1;
  1593.             vec3_t          p2;
  1594.             vec3_t          v1;
  1595.             vec3_t          v2;
  1596.             vec3_t          vspot;
  1597.             unsigned        prev_edge;
  1598.             unsigned        next_edge;
  1599.             int             e;
  1600.             int             e1;
  1601.             int             e2;
  1602.             edgeshare_t*    es;
  1603.             edgeshare_t*    es1;
  1604.             edgeshare_t*    es2;
  1605.             float           a1;
  1606.             float           a2;
  1607.             float           aa;
  1608.             float           bb;
  1609.             float           ab;
  1610.  
  1611.             if (j)
  1612.             {
  1613.                 prev_edge = f->firstedge + ((j - 1) % f->numedges);
  1614.             }
  1615.             else
  1616.             {
  1617.                 prev_edge = f->firstedge + f->numedges - 1;
  1618.             }
  1619.  
  1620.             if ((j + 1) != f->numedges)
  1621.             {
  1622.                 next_edge = f->firstedge + ((j + 1) % f->numedges);
  1623.             }
  1624.             else
  1625.             {
  1626.                 next_edge = f->firstedge;
  1627.             }
  1628.  
  1629.             e = g_dsurfedges[f->firstedge + j];
  1630.             e1 = g_dsurfedges[prev_edge];
  1631.             e2 = g_dsurfedges[next_edge];
  1632.  
  1633.             es = &g_edgeshare[abs(e)];
  1634.             es1 = &g_edgeshare[abs(e1)];
  1635.             es2 = &g_edgeshare[abs(e2)];
  1636.  
  1637.             if (
  1638.                 (es->coplanar && es1->coplanar && es2->coplanar)
  1639.                 ||
  1640.                 (VectorCompare(es->interface_normal, vec3_origin) &&
  1641.                  VectorCompare(es1->interface_normal, vec3_origin) &&
  1642.                  VectorCompare(es2->interface_normal, vec3_origin)))
  1643.             {
  1644.                 continue;
  1645.             }
  1646.  
  1647.             if (e > 0)
  1648.             {
  1649.                 VectorCopy(g_dvertexes[g_dedges[e].v[0]].point, p1);
  1650.                 VectorCopy(g_dvertexes[g_dedges[e].v[1]].point, p2);
  1651.             }
  1652.             else
  1653.             {
  1654.                 VectorCopy(g_dvertexes[g_dedges[-e].v[1]].point, p1);
  1655.                 VectorCopy(g_dvertexes[g_dedges[-e].v[0]].point, p2);
  1656.             }
  1657.  
  1658.             // Adjust for origin-based models
  1659.             VectorAdd(p1, g_face_offset[facenum], p1);
  1660.             VectorAdd(p2, g_face_offset[facenum], p2);
  1661.  
  1662.             // Build vectors from the middle of the face to the edge vertexes and the sample pos.
  1663.             VectorSubtract(p1, g_face_centroids[facenum], v1);
  1664.             VectorSubtract(p2, g_face_centroids[facenum], v2);
  1665.             VectorSubtract(spot, g_face_centroids[facenum], vspot);
  1666.  
  1667.             aa = DotProduct(v1, v1);
  1668.             bb = DotProduct(v2, v2);
  1669.             ab = DotProduct(v1, v2);
  1670.             a1 = (bb * DotProduct(v1, vspot) - ab * DotProduct(vspot, v2)) / (aa * bb - ab * ab);
  1671.             a2 = (DotProduct(vspot, v2) - a1 * ab) / bb;
  1672.  
  1673.             // Test center to sample vector for inclusion between center to vertex vectors (Use dot product of vectors)
  1674.             if (a1 >= 0.0 && a2 >= 0.0)
  1675.             {
  1676.                 // calculate distance from edge to pos
  1677.                 vec3_t          n1, n2;
  1678.                 vec3_t          temp;
  1679.  
  1680.                 VectorAdd(es->interface_normal, es1->interface_normal, n1);
  1681.  
  1682.                 if (VectorCompare(n1, vec3_origin))
  1683.                 {
  1684.                     VectorCopy(facenormal, n1);
  1685.                 }
  1686.                 VectorNormalize(n1);
  1687.  
  1688.                 VectorAdd(es->interface_normal, es2->interface_normal, n2);
  1689.  
  1690.                 if (VectorCompare(n2, vec3_origin))
  1691.                 {
  1692.                     VectorCopy(facenormal, n2);
  1693.                 }
  1694.                 VectorNormalize(n2);
  1695.  
  1696.                 // Interpolate between the center and edge normals based on sample position
  1697.                 VectorScale(facenormal, 1.0 - a1 - a2, phongnormal);
  1698.                 VectorScale(n1, a1, temp);
  1699.                 VectorAdd(phongnormal, temp, phongnormal);
  1700.                 VectorScale(n2, a2, temp);
  1701.                 VectorAdd(phongnormal, temp, phongnormal);
  1702.                 VectorNormalize(phongnormal);
  1703.                 break;
  1704.             }
  1705.         }
  1706.     }
  1707. }
  1708.  
  1709. const vec3_t    s_circuscolors[] = {
  1710.     {100000.0,  100000.0,   100000.0},                              // white
  1711.     {100000.0,  0.0,        0.0     },                              // red
  1712.     {0.0,       100000.0,   0.0     },                              // green
  1713.     {0.0,       0.0,        100000.0},                              // blue
  1714.     {0.0,       100000.0,   100000.0},                              // cyan
  1715.     {100000.0,  0.0,        100000.0},                              // magenta
  1716.     {100000.0,  100000.0,   0.0     }                               // yellow
  1717. };
  1718.  
  1719. // =====================================================================================
  1720. //  BuildFacelights
  1721. // =====================================================================================
  1722. void            BuildFacelights(const int facenum)
  1723. {
  1724.     dface_t*        f;
  1725.     vec3_t          sampled[MAXLIGHTMAPS];
  1726.     lightinfo_t     l;
  1727.     int             i;
  1728.     int             j;
  1729.     int             k;
  1730.     sample_t*       s;
  1731.     vec_t*          spot;
  1732.     patch_t*        patch;
  1733.     const dplane_t* plane;
  1734.     byte            pvs[(MAX_MAP_LEAFS + 7) / 8];
  1735.     int             thisoffset = -1, lastoffset = -1;
  1736.     int             lightmapwidth;
  1737.     int             lightmapheight;
  1738.     int             size;
  1739.  
  1740. #ifdef HLRAD_HULLU
  1741.     bool            b_transparency_loss = false;
  1742.     vec_t           light_left_for_facelight = 1.0;
  1743. #endif
  1744.  
  1745.     f = &g_dfaces[facenum];
  1746.  
  1747.     //
  1748.     // some surfaces don't need lightmaps
  1749.     //
  1750.     f->lightofs = -1;
  1751.     for (j = 0; j < MAXLIGHTMAPS; j++)
  1752.     {
  1753.         f->styles[j] = 255;
  1754.     }
  1755.  
  1756.     if (g_texinfo[f->texinfo].flags & TEX_SPECIAL)
  1757.     {
  1758.         return;                                            // non-lit texture
  1759.     }
  1760.  
  1761.     f->styles[0] = 0;                                      // Everyone gets the style zero map.
  1762.  
  1763.     memset(&l, 0, sizeof(l));
  1764.  
  1765.     l.surfnum = facenum;
  1766.     l.face = f;
  1767.  
  1768.     //
  1769.     // get transparency loss (part of light go through transparency faces.. reduce facelight on these)
  1770.     //
  1771. #ifdef HLRAD_HULLU
  1772.     for(unsigned int m = 0; m < g_opaque_face_count; m++)
  1773.     {
  1774.         opaqueList_t* opaque = &g_opaque_face_list[m];
  1775.         if(opaque->facenum == facenum && opaque->transparency)
  1776.         {
  1777.             vec_t transparency = opaque->transparency;
  1778.             
  1779.             b_transparency_loss = true;
  1780.             
  1781.             light_left_for_facelight = 1.0 - transparency;
  1782.             if( light_left_for_facelight < 0.0 ) light_left_for_facelight = 0.0;
  1783.             if( light_left_for_facelight > 1.0 ) light_left_for_facelight = 1.0;
  1784.             
  1785.             break;
  1786.         }
  1787.     }
  1788. #endif
  1789.  
  1790.     //
  1791.     // rotate plane
  1792.     //
  1793.     plane = getPlaneFromFace(f);
  1794.     VectorCopy(plane->normal, l.facenormal);
  1795.     l.facedist = plane->dist;
  1796.  
  1797.     CalcFaceVectors(&l);
  1798.     CalcFaceExtents(&l);
  1799.     CalcPoints(&l);
  1800.  
  1801.     lightmapwidth = l.texsize[0] + 1;
  1802.     lightmapheight = l.texsize[1] + 1;
  1803.  
  1804.     size = lightmapwidth * lightmapheight;
  1805.     hlassume(size <= MAX_SINGLEMAP, assume_MAX_SINGLEMAP);
  1806.  
  1807.     facelight[facenum].numsamples = l.numsurfpt;
  1808.  
  1809.     for (k = 0; k < MAXLIGHTMAPS; k++)
  1810.     {
  1811.         facelight[facenum].samples[k] = (sample_t*)calloc(l.numsurfpt, sizeof(sample_t));
  1812.     }
  1813.  
  1814.     spot = l.surfpt[0];
  1815.     for (i = 0; i < l.numsurfpt; i++, spot += 3)
  1816.     {
  1817.         vec3_t          pointnormal = { 0, 0, 0 };
  1818.  
  1819.         for (k = 0; k < MAXLIGHTMAPS; k++)
  1820.         {
  1821.             VectorCopy(spot, facelight[facenum].samples[k][i].pos);
  1822.         }
  1823.  
  1824.         // get the PVS for the pos to limit the number of checks
  1825.         if (!g_visdatasize)
  1826.         {
  1827.             memset(pvs, 255, (g_numleafs + 7) / 8);
  1828.             lastoffset = -1;
  1829.         }
  1830.         else
  1831.         {
  1832.             dleaf_t*        leaf = PointInLeaf(spot);
  1833.  
  1834.             thisoffset = leaf->visofs;
  1835.             if (i == 0 || thisoffset != lastoffset)
  1836.             {
  1837.                 hlassert(thisoffset != -1);
  1838.                 DecompressVis(&g_dvisdata[leaf->visofs], pvs, sizeof(pvs));
  1839.             }
  1840.             lastoffset = thisoffset;
  1841.         }
  1842.  
  1843.         memset(sampled, 0, sizeof(sampled));
  1844.  
  1845.         // If we are doing "extra" samples, oversample the direct light around the point.
  1846.         if (g_extra)
  1847.         {
  1848.             int             weighting[3][3] = { {5, 9, 5}, {9, 16, 9}, {5, 9, 5} };
  1849.             vec3_t          pos;
  1850.             int             s, t, subsamples = 0;
  1851.  
  1852.             for (t = -1; t <= 1; t++)
  1853.             {
  1854.                 for (s = -1; s <= 1; s++)
  1855.                 {
  1856.                     int             subsample = i + t * lightmapwidth + s;
  1857.                     int             sample_s = i % lightmapwidth;
  1858.                     int sample_t = i / lightmapwidth;
  1859.  
  1860.                     if ((0 <= s + sample_s) && (s + sample_s < lightmapwidth)
  1861.                         && (0 <= t + sample_t)&&(t + sample_t <lightmapheight))
  1862.                     {
  1863.                         vec3_t          subsampled[MAXLIGHTMAPS];
  1864.  
  1865.                         for (j = 0; j < MAXLIGHTMAPS; j++)
  1866.                         {
  1867.                             VectorFill(subsampled[j], 0);
  1868.                         }
  1869.  
  1870.                         // Calculate the point one third of the way toward the "subsample point"
  1871.                         VectorCopy(l.surfpt[i], pos);
  1872.                         VectorAdd(pos, l.surfpt[i], pos);
  1873.                         VectorAdd(pos, l.surfpt[subsample], pos);
  1874.                         VectorScale(pos, 1.0 / 3.0, pos);
  1875.  
  1876.                         GetPhongNormal(facenum, pos, pointnormal);
  1877.                         GatherSampleLight(pos, pvs, pointnormal, subsampled, f->styles);
  1878.                         for (j = 0; j < MAXLIGHTMAPS && (f->styles[j] != 255); j++)
  1879.                         {
  1880.                             VectorScale(subsampled[j], weighting[s + 1][t + 1], subsampled[j]);
  1881.                             VectorAdd(sampled[j], subsampled[j], sampled[j]);
  1882.                         }
  1883.                         subsamples += weighting[s + 1][t + 1];
  1884.                     }
  1885.                 }
  1886.             }
  1887.             for (j = 0; j < MAXLIGHTMAPS && (f->styles[j] != 255); j++)
  1888.             {
  1889.                 VectorScale(sampled[j], 1.0 / subsamples, sampled[j]);
  1890.             }
  1891.         }
  1892.         else
  1893.         {
  1894.             GetPhongNormal(facenum, spot, pointnormal);
  1895.             GatherSampleLight(spot, pvs, pointnormal, sampled, f->styles);
  1896.         }
  1897.  
  1898.         for (j = 0; j < MAXLIGHTMAPS && (f->styles[j] != 255); j++)
  1899.         {
  1900.             VectorCopy(sampled[j], facelight[facenum].samples[j][i].light);
  1901.  
  1902. #ifdef HLRAD_HULLU            
  1903.             if(b_transparency_loss)
  1904.             {
  1905.                  VectorScale(facelight[facenum].samples[j][i].light, light_left_for_facelight, facelight[facenum].samples[j][i].light);
  1906.             }
  1907. #endif
  1908.  
  1909. #ifdef ZHLT_TEXLIGHT
  1910.             AddSampleToPatch(&facelight[facenum].samples[j][i], facenum, f->styles[j]); //LRC
  1911. #else
  1912.             if (f->styles[j] == 0)
  1913.             {
  1914.                 AddSampleToPatch(&facelight[facenum].samples[j][i], facenum);
  1915.             }
  1916. #endif
  1917.         }
  1918.     }
  1919.  
  1920.     // average up the direct light on each patch for radiosity
  1921.     if (g_numbounce > 0)
  1922.     {
  1923.         for (patch = g_face_patches[facenum]; patch; patch = patch->next)
  1924.         {
  1925. #ifdef ZHLT_TEXLIGHT
  1926.             //LRC:
  1927.             unsigned istyle;
  1928.             for (istyle = 0; istyle < MAXLIGHTMAPS && patch->totalstyle[istyle] != 255; istyle++)
  1929.             {
  1930.                 if (patch->samples[istyle])
  1931.                 {
  1932.                     vec3_t          v;                         // BUGBUG: Use a weighted average instead?
  1933.  
  1934.                     VectorScale(patch->samplelight[istyle], (1.0f / patch->samples[istyle]), v);
  1935.                     VectorAdd(patch->totallight[istyle], v, patch->totallight[istyle]);
  1936.                     VectorAdd(patch->directlight[istyle], v, patch->directlight[istyle]);
  1937.                 }
  1938.             }
  1939.             //LRC (ends)
  1940. #else
  1941.             if (patch->samples)
  1942.             {
  1943.                 vec3_t          v;                         // BUGBUG: Use a weighted average instead?
  1944.  
  1945.                 VectorScale(patch->samplelight, (1.0f / patch->samples), v);
  1946.                 VectorAdd(patch->totallight, v, patch->totallight);
  1947.                 VectorAdd(patch->directlight, v, patch->directlight);
  1948.             }
  1949. #endif
  1950.         }
  1951.     }
  1952.  
  1953.     // add an ambient term if desired
  1954.     if (g_ambient[0] || g_ambient[1] || g_ambient[2])
  1955.     {
  1956.         for (j = 0; j < MAXLIGHTMAPS && f->styles[j] != 255; j++)
  1957.         {
  1958.             if (f->styles[j] == 0)
  1959.             {
  1960.                 s = facelight[facenum].samples[j];
  1961.                 for (i = 0; i < l.numsurfpt; i++, s++)
  1962.                 {
  1963.                     VectorAdd(s->light, g_ambient, s->light);
  1964.                 }
  1965.                 break;
  1966.             }
  1967.         }
  1968.  
  1969.     }
  1970.  
  1971.     // add circus lighting for finding black lightmaps
  1972.     if (g_circus)
  1973.     {
  1974.         for (j = 0; j < MAXLIGHTMAPS && f->styles[j] != 255; j++)
  1975.         {
  1976.             if (f->styles[j] == 0)
  1977.             {
  1978.                 int             amt = 7;
  1979.  
  1980.                 s = facelight[facenum].samples[j];
  1981.  
  1982.                 while ((l.numsurfpt % amt) == 0)
  1983.                 {
  1984.                     amt--;
  1985.                 }
  1986.                 if (amt < 2)
  1987.                 {
  1988.                     amt = 7;
  1989.                 }
  1990.  
  1991.                 for (i = 0; i < l.numsurfpt; i++, s++)
  1992.                 {
  1993.                     if ((s->light[0] == 0) && (s->light[1] == 0) && (s->light[2] == 0))
  1994.                     {
  1995.                         VectorAdd(s->light, s_circuscolors[i % amt], s->light);
  1996.                     }
  1997.                 }
  1998.                 break;
  1999.             }
  2000.         }
  2001.     }
  2002.  
  2003.     // light from dlight_threshold and above is sent out, but the
  2004.     // texture itself should still be full bright
  2005.  
  2006.     // if( VectorAvg( face_patches[facenum]->baselight ) >= dlight_threshold)       // Now all lighted surfaces glow
  2007.     {
  2008. #ifdef ZHLT_TEXLIGHT
  2009.         //LRC:
  2010.         if (g_face_patches[facenum])
  2011.         {
  2012.             for (j = 0; j < MAXLIGHTMAPS && f->styles[j] != 255; j++)
  2013.             {
  2014.                 if (f->styles[j] == g_face_patches[facenum]->emitstyle) //LRC
  2015.                 {
  2016.                     break;
  2017.                 }
  2018.             }
  2019.  
  2020.             if (j == MAXLIGHTMAPS)
  2021.             {
  2022.                 Warning("Too many direct light styles on a face(?,?,?)");
  2023.             }
  2024.             else
  2025.             {
  2026.                 if (f->styles[j] == 255)
  2027.                 {
  2028.                     f->styles[j] = g_face_patches[facenum]->emitstyle;
  2029.                 }
  2030.  
  2031.                 s = facelight[facenum].samples[j];
  2032.                 for (i = 0; i < l.numsurfpt; i++, s++)
  2033.                 {
  2034.                     VectorAdd(s->light, g_face_patches[facenum]->baselight, s->light);
  2035.                 }
  2036.             }
  2037.         }
  2038.         //LRC (ends)
  2039. #else
  2040.         for (j = 0; j < MAXLIGHTMAPS && f->styles[j] != 255; j++)
  2041.         {
  2042.             if (f->styles[j] == 0)
  2043.             {
  2044.                 if (g_face_patches[facenum])
  2045.                 {
  2046.                     s = facelight[facenum].samples[j];
  2047.                     for (i = 0; i < l.numsurfpt; i++, s++)
  2048.                     {
  2049.                         VectorAdd(s->light, g_face_patches[facenum]->baselight, s->light);
  2050.                     }
  2051.                     break;
  2052.                 }
  2053.             }
  2054.         }
  2055. #endif
  2056.     }
  2057. }
  2058.  
  2059. // =====================================================================================
  2060. //  PrecompLightmapOffsets
  2061. // =====================================================================================
  2062. void            PrecompLightmapOffsets()
  2063. {
  2064.     int             facenum;
  2065.     dface_t*        f;
  2066.     facelight_t*    fl;
  2067.     int             lightstyles;
  2068.  
  2069. #ifdef ZHLT_TEXLIGHT
  2070.     int             i; //LRC
  2071.     patch_t*        patch; //LRC
  2072. #endif
  2073.  
  2074.     g_lightdatasize = 0;
  2075.  
  2076.     for (facenum = 0; facenum < g_numfaces; facenum++)
  2077.     {
  2078.         f = &g_dfaces[facenum];
  2079.         fl = &facelight[facenum];
  2080.  
  2081.         if (g_texinfo[f->texinfo].flags & TEX_SPECIAL)
  2082.         {
  2083.             continue;                                      // non-lit texture
  2084.         }
  2085.  
  2086. #ifdef ZHLT_TEXLIGHT
  2087.                 //LRC - find all the patch lightstyles, and add them to the ones used by this face
  2088.         patch = g_face_patches[facenum];
  2089.         if (patch)
  2090.         {
  2091.             for (i = 0; i < MAXLIGHTMAPS && patch->totalstyle[i] != 255; i++)
  2092.             {
  2093.                 for (lightstyles = 0; lightstyles < MAXLIGHTMAPS && f->styles[lightstyles] != 255; lightstyles++)
  2094.                 {
  2095.                     if (f->styles[lightstyles] == patch->totalstyle[i])
  2096.                         break;
  2097.                 }
  2098.                 if (lightstyles == MAXLIGHTMAPS)
  2099.                 {
  2100.                     Warning("Too many direct light styles on a face(?,?,?)\n");
  2101.                 }
  2102.                 else if (f->styles[lightstyles] == 255)
  2103.                 {
  2104.                     f->styles[lightstyles] = patch->totalstyle[i];
  2105. //                    Log("Face acquires new lightstyle %d at offset %d\n", f->styles[lightstyles], lightstyles);
  2106.                 }
  2107.             }
  2108.         }
  2109.         //LRC (ends)
  2110. #endif
  2111.  
  2112.         for (lightstyles = 0; lightstyles < MAXLIGHTMAPS; lightstyles++)
  2113.         {
  2114.             if (f->styles[lightstyles] == 255)
  2115.             {
  2116.                 break;
  2117.             }
  2118.         }
  2119.  
  2120.         if (!lightstyles)
  2121.         {
  2122.             continue;
  2123.         }
  2124.  
  2125.         f->lightofs = g_lightdatasize;
  2126.         g_lightdatasize += fl->numsamples * 3 * lightstyles;
  2127.     }
  2128. }
  2129.  
  2130. // =====================================================================================
  2131. //  FinalLightFace
  2132. //      Add the indirect lighting on top of the direct lighting and save into final map format
  2133. // =====================================================================================
  2134. void            FinalLightFace(const int facenum)
  2135. {
  2136.     int             i, j, k;
  2137.     vec3_t          lb, v;
  2138.     facelight_t*    fl;
  2139.     sample_t*       samp;
  2140.     float           minlight;
  2141.     int             lightstyles;
  2142.     dface_t*        f;
  2143.     lerpTriangulation_t* trian = NULL;
  2144.  
  2145.     // ------------------------------------------------------------------------
  2146.     // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  2147. #ifdef HLRAD_WHOME
  2148.     float           temp_rand;
  2149. #endif
  2150.     // ------------------------------------------------------------------------
  2151.  
  2152.     f = &g_dfaces[facenum];
  2153.     fl = &facelight[facenum];
  2154.  
  2155.     if (g_texinfo[f->texinfo].flags & TEX_SPECIAL)
  2156.     {
  2157.         return;                                            // non-lit texture
  2158.     }
  2159.  
  2160.     for (lightstyles = 0; lightstyles < MAXLIGHTMAPS; lightstyles++)
  2161.     {
  2162.         if (f->styles[lightstyles] == 255)
  2163.         {
  2164.             break;
  2165.         }
  2166.     }
  2167.  
  2168.     if (!lightstyles)
  2169.     {
  2170.         return;
  2171.     }
  2172.  
  2173.     //
  2174.     // set up the triangulation
  2175.     //
  2176.     if (g_numbounce)
  2177.     {
  2178.         trian = CreateTriangulation(facenum);
  2179.     }
  2180.     //
  2181.     // sample the triangulation
  2182.     //
  2183.     minlight = FloatForKey(g_face_entity[facenum], "_minlight") * 128;
  2184.  
  2185.     for (k = 0; k < lightstyles; k++)
  2186.     {
  2187.         samp = fl->samples[k];
  2188.         for (j = 0; j < fl->numsamples; j++, samp++)
  2189.         {
  2190.             // Should be a VectorCopy, but we scale by 2 to compensate for an earlier lighting flaw
  2191.             // Specifically, the directlight contribution was included in the bounced light AND the directlight
  2192.             // Since many of the levels were built with this assumption, this "fudge factor" compensates for it.
  2193.  
  2194.             VectorScale(samp->light, g_direct_scale, lb);
  2195.  
  2196. #ifdef ZHLT_TEXLIGHT
  2197.             if (g_numbounce)//LRC && (k == 0))
  2198.             {
  2199.                 SampleTriangulation(trian, samp->pos, v, f->styles[k]); //LRC
  2200. #else
  2201.             if (g_numbounce && (k == 0))
  2202.             {
  2203.                 SampleTriangulation(trian, samp->pos, v);
  2204. #endif
  2205.  
  2206.                 if (isPointFinite(v))
  2207.                 {
  2208.                     VectorAdd(lb, v, lb);
  2209.                 }
  2210.                 else
  2211.                 {
  2212.                     Warning("point (%4.3f %4.3f %4.3f) infinite v (%4.3f %4.3f %4.3f)\n",
  2213.                             samp->pos[0], samp->pos[1], samp->pos[2], v[0], v[1], v[2]);
  2214.                 }
  2215.  
  2216.  
  2217.             }
  2218.  
  2219.             // ------------------------------------------------------------------------
  2220.             // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  2221.             // colour lightscale - code was originally:
  2222. #ifdef HLRAD_WHOME
  2223.             lb[0] *= g_colour_lightscale[0];
  2224.             lb[1] *= g_colour_lightscale[1];
  2225.             lb[2] *= g_colour_lightscale[2];
  2226. #else
  2227.             VectorScale(lb, g_lightscale, lb);
  2228. #endif
  2229.             // ------------------------------------------------------------------------
  2230.  
  2231.             // clip from the bottom first
  2232.             for (i = 0; i < 3; i++)
  2233.             {
  2234.                 if (lb[i] < minlight)
  2235.                 {
  2236.                     lb[i] = minlight;
  2237.                 }
  2238.             }
  2239.  
  2240.             // clip from the top
  2241.             {
  2242.                 vec_t           max = VectorMaximum(lb);
  2243.  
  2244.                 if (max > g_maxlight)
  2245.                 {
  2246.                     vec_t           scale = g_maxlight / max;
  2247.  
  2248.                     lb[0] *= scale;
  2249.                     lb[1] *= scale;
  2250.                     lb[2] *= scale;
  2251.                 }
  2252.             }
  2253.  
  2254.             // ------------------------------------------------------------------------
  2255.             // Changes by Adam Foster - afoster@compsoc.man.ac.uk
  2256. #ifdef HLRAD_WHOME
  2257.  
  2258.             // AJM: your code is formatted really wierd, and i cant understand a damn thing. 
  2259.             //      so i reformatted it into a somewhat readable "normal" fashion. :P
  2260.  
  2261.             // colour gamma  - code was originally:
  2262.             //   if (g_qgamma != 1.0) {
  2263.             //       for (i = 0; i < 3; i++) {
  2264.             //           lb[i] = (float) pow(lb[i] / 256.0f, g_qgamma) * 256.0f;
  2265.             //         }
  2266.             //   }
  2267.  
  2268.             if ( g_colour_qgamma[0] != 1.0 ) 
  2269.                 lb[0] = (float) pow(lb[0] / 256.0f, g_colour_qgamma[0]) * 256.0f;
  2270.  
  2271.             if ( g_colour_qgamma[1] != 1.0 ) 
  2272.                 lb[1] = (float) pow(lb[1] / 256.0f, g_colour_qgamma[1]) * 256.0f;
  2273.  
  2274.             if ( g_colour_qgamma[2] != 1.0 ) 
  2275.                 lb[2] = (float) pow(lb[2] / 256.0f, g_colour_qgamma[2]) * 256.0f;
  2276.  
  2277.             // Two different ways of adding noise to the lightmap - colour jitter
  2278.             // (red, green and blue channels are independent), and mono jitter
  2279.             // (monochromatic noise). For simulating dithering, on the cheap. :)
  2280.  
  2281.             // Tends to create seams between adjacent polygons, so not ideal.
  2282.  
  2283.             // Got really weird results when it was set to limit values to 256.0f - it
  2284.             // was as if r, g or b could wrap, going close to zero.
  2285.  
  2286.             if (g_colour_jitter_hack[0] || g_colour_jitter_hack[1] || g_colour_jitter_hack[2]) 
  2287.             {
  2288.                 for (i = 0; i < 3; i++) 
  2289.                 {
  2290.                     lb[i] += g_colour_jitter_hack[i] * ((float)rand() / RAND_MAX - 0.5);
  2291.                     if (lb[i] < 0.0f)
  2292.                     {
  2293.                         lb[i] = 0.0f;
  2294.                     }
  2295.                     else if (lb[i] > 255.0f)
  2296.                     {
  2297.                         lb[i] = 255.0f;
  2298.                     }
  2299.                 }
  2300.             }
  2301.  
  2302.             if (g_jitter_hack[0] || g_jitter_hack[1] || g_jitter_hack[2]) 
  2303.             {
  2304.                 temp_rand = (float)rand() / RAND_MAX - 0.5;
  2305.                 for (i = 0; i < 3; i++) 
  2306.                 {
  2307.                     lb[i] += g_jitter_hack[i] * temp_rand;
  2308.                     if (lb[i] < 0.0f)
  2309.                     {
  2310.                         lb[i] = 0.0f;
  2311.                     }
  2312.                     else if (lb[i] > 255.0f)
  2313.                     {
  2314.                         lb[i] = 255.0f;
  2315.                     }
  2316.                 }
  2317.             }
  2318. #else
  2319.             if (g_qgamma != 1.0) {
  2320.                 for (i = 0; i < 3; i++) {
  2321.                     lb[i] = (float) pow(lb[i] / 256.0f, g_qgamma) * 256.0f;
  2322.                 }
  2323.             }
  2324. #endif
  2325.             // ------------------------------------------------------------------------
  2326.  
  2327.             {
  2328.                 unsigned char* colors = &g_dlightdata[f->lightofs + k * fl->numsamples * 3 + j * 3];
  2329.  
  2330.                 colors[0] = (unsigned char)lb[0];
  2331.                 colors[1] = (unsigned char)lb[1];
  2332.                 colors[2] = (unsigned char)lb[2];
  2333.             }
  2334.         }
  2335.     }
  2336.  
  2337.     if (g_numbounce)
  2338.     {
  2339.         FreeTriangulation(trian);
  2340.     }
  2341. }
  2342.  
  2343.  
  2344. #ifdef ZHLT_TEXLIGHT
  2345. //LRC
  2346. vec3_t    totallight_default = { 0, 0, 0 };
  2347.  
  2348. //LRC - utility for getting the right totallight value from a patch
  2349. vec3_t* GetTotalLight(patch_t* patch, int style)
  2350. {
  2351.     int i;
  2352.     for (i = 0; i < MAXLIGHTMAPS && patch->totalstyle[i] != 255; i++)
  2353.     {
  2354.         if (patch->totalstyle[i] == style)
  2355.             return &(patch->totallight[i]);
  2356.     }
  2357.     return &totallight_default;
  2358. }
  2359.  
  2360. #endif
  2361.